package com.csdware.mdviewer;


import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.OpenableColumns;
import android.provider.Settings;
import android.view.KeyEvent;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.csdware.mdviewer.lib_Nanohttpd.protocols.http.NanoHTTPD;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Objects;

public class MainActivity extends AppCompatActivity {
    public static final int REQUEST_CODE_NATIVE_FILE_CHOOSER = 1005;
    public static final String SHARE_CACHE_FOLDER_NAME = "MDViewerDocCache";
    Service_HttpServer Server;
    private WebView NoteWebView;
    SharedPreferences sharedPreferences;
    String MDPathCache_ForInstanceSaving = "";
    int CurrentScale = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTheme(R.style.Theme_MDViewer);
        setContentView(R.layout.activity_main);
        RequestStoragePermission(MainActivity.this);
        sharedPreferences = getSharedPreferences("Settings", Context.MODE_PRIVATE);
        // 设置全屏
        EdgeToEdge.enable(this);
        if (android.os.Build.VERSION.SDK_INT >= 30) {
            WindowInsetsController windowInsetsController = getWindow().getInsetsController();
            if (windowInsetsController != null) {
                windowInsetsController.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
                windowInsetsController.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
            }
        }
        // Webview初始化
        NoteWebView = findViewById(R.id.NoteWebView);
        WebSettings webSettings = NoteWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);  // 注释掉就运行不了Javascript代码了
        webSettings.setDomStorageEnabled(true);  // 启用DOM存储API
        webSettings.setSupportZoom(true);           // 启用双指缩放三者缺一不可
        webSettings.setBuiltInZoomControls(true);   // 启用双指缩放三者缺一不可
        webSettings.setDisplayZoomControls(false);  // 启用双指缩放三者缺一不可
        NoteWebView.setWebViewClient(new WebViewClient());  // 设置WebView客户端，让页面在WebView中打开而不是外部浏览器
        NoteWebView.setWebChromeClient(new WebChromeClient());  // 设置WebChromeClient以支持JavaScript对话框等

        BindSettingWidgetCallbacks();

        // 启动阅览服务
        if (savedInstanceState == null) {  // 场景1：首次启动应用（或进程被杀死后重新启动）
            TheUserWantsToOpenANewFile(ParseUriFile(getIntent()));
        } else {  // 场景2：因配置变化（如屏幕旋转）导致的Activity重建
            TheUserWantsToOpenANewFile(savedInstanceState.getString("MDPath"));
        }

        // 拦截返回事件
        getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                moveTaskToBack(true);
            }
        });
    }

    @Override
    protected void onStop() {
        if (Server != null) Server.stop();
        super.onStop();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        TheUserWantsToOpenANewFile(ParseUriFile(intent));
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_NATIVE_FILE_CHOOSER && resultCode == RESULT_OK) {
            String fp = ParseUriFile(data);
            if (!fp.isEmpty()) {
                SharedPreferences sharedPreferences = getSharedPreferences("Settings", Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putString("CSSPath", fp);
                editor.apply();
                TextView TextView_CurrentCSSDisplay = findViewById(R.id.CurrentCSSDisplay);
                TextView_CurrentCSSDisplay.setText(fp);
            }
        }
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("MDPath", MDPathCache_ForInstanceSaving);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
            if (sharedPreferences.getBoolean("AllowVolumeZoomControl", true)) {
                CurrentScale += 10;
                NoteWebView.setInitialScale(CurrentScale);
                NoteWebView.loadUrl("http://localhost:" + sharedPreferences.getInt("Port", 8889) + "/index.html");
                Toast.makeText(MainActivity.this, getString(R.string.scale) + CurrentScale, Toast.LENGTH_SHORT).show();
                return true; // 拦截系统默认行为
            }
        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            if (sharedPreferences.getBoolean("AllowVolumeZoomControl", true)) {
                CurrentScale -= 10;
                NoteWebView.setInitialScale(CurrentScale);
                NoteWebView.loadUrl("http://localhost:" + sharedPreferences.getInt("Port", 8889) + "/index.html");
                Toast.makeText(MainActivity.this, getString(R.string.scale) + CurrentScale, Toast.LENGTH_SHORT).show();
                return true; // 拦截系统默认行为
            }
        }
        return super.onKeyDown(keyCode, event);  // 其他按键事件交给系统处理
    }

    public void TheUserWantsToOpenANewFile(String Path) {
        if (Objects.equals(Path, "")) return;
        // ======= 当用户想要打开一个新的文件时，关闭所有服务，然后完全重新加载 =======
        // 变量初始化
        MDPathCache_ForInstanceSaving = Path;
        FrameLayout ActivityMainRoot = findViewById(R.id.ActivityMainRoot);
        LinearLayout NoteWebViewPaddingController = findViewById(R.id.NoteWebViewPaddingController);
        ScrollView SettingsOverlay = findViewById(R.id.SettingsOverlay);
        ActivityMainRoot.removeView(SettingsOverlay);
        // 重启文件服务器
        if (Server != null) Server.stop();
        String ServerIP = sharedPreferences.getBoolean("AllowExternalAccess", false) ? "0.0.0.0" : "127.0.0.1";  // 0.0.0.0允许局域网所有设备访问，127.0.0.1只允许本机访问
        Server = new Service_HttpServer(this, ServerIP, sharedPreferences.getInt("Port", 8889), "LocalWebServerAssets", Path);
        try {
            Server.start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 设置缩放
        int orientation = getResources().getConfiguration().orientation;
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            CurrentScale = sharedPreferences.getInt("LandscapeDisplayScale", 200);
        } else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            CurrentScale = sharedPreferences.getInt("DisplayScale", 120);
        }
        NoteWebView.setInitialScale(CurrentScale);
        // 设置边距
        float paddingDP = sharedPreferences.getInt("Padding", 0);
        float paddingDPTop = sharedPreferences.getInt("PaddingTop", 20);
        float density = getResources().getDisplayMetrics().density;
        int paddingPX = (int) (paddingDP * density);
        int paddingPXTop = (int) (paddingDPTop * density);
        NoteWebViewPaddingController.setPadding(paddingPX, paddingPXTop, paddingPX, paddingPX);
        // 加载
        NoteWebView.loadUrl("http://localhost:" + sharedPreferences.getInt("Port", 8889) + "/index.html");
    }

    private String ParseUriFile(Intent intent) {
        Bundle extras = intent.getExtras();
        if (extras != null) {
            Object streamObject = extras.get(Intent.EXTRA_STREAM);
            if (streamObject instanceof ArrayList<?>) { // *****多文件的处理*****
                StringBuilder filePath_all = new StringBuilder();
                ArrayList<Parcelable> uris = (ArrayList<Parcelable>) streamObject;
                for (Parcelable uri : uris) {
                    if (uri instanceof Uri) {
                        // 处理每个 URI，这里你可以进行你需要的操作
                        String filePath_individual = Func_TryUriConvert.Convert((Uri) uri, MainActivity.this);
                        if (Objects.equals(filePath_individual, "")) {
                            filePath_individual = copyUriToFile((Uri) uri);
                        }
                        if (Objects.equals(filePath_all.toString(), "")) {
                            filePath_all = new StringBuilder(filePath_individual);
                        } else {
                            filePath_all.append("-//-").append(filePath_individual);
                        }
                    }
                }
                return filePath_all.toString();
            } else { // *****单文件的处理*****
                Uri uri = extras.getParcelable(Intent.EXTRA_STREAM);
                if (uri == null) {
                    Uri uri2 = intent.getData();
                    if (uri2 != null) {
                        String filePath = Func_TryUriConvert.Convert(uri2, MainActivity.this);
                        if (Objects.equals(filePath, "")) {
                            filePath = copyUriToFile(uri2);
                        }
                        return filePath;
                    }
                } else {
                    String filePath = Func_TryUriConvert.Convert(uri, MainActivity.this);
                    if (Objects.equals(filePath, "")) {
                        filePath = copyUriToFile(uri);
                    }
                    return filePath;
                }
            }
        } else {
            Uri uri = intent.getData();
            if (uri != null) {
                String filePath = Func_TryUriConvert.Convert(uri, MainActivity.this);
                if (Objects.equals(filePath, "")) {
                    filePath = copyUriToFile(uri);
                }
                return filePath;
            }
        }
        return "";
    }

    private String copyUriToFile(Uri uri) {
        try {
            InputStream inputStream = MainActivity.this.getContentResolver().openInputStream(uri);
            if (inputStream != null) {
                File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), SHARE_CACHE_FOLDER_NAME);
                if (!dir.exists()) {
                    if (!dir.mkdirs()) {
                        return "";
                    }
                }
                String fileName = getFileNameFromUri(uri);
                File file = new File(dir, fileName);
                FileOutputStream outputStream = new FileOutputStream(file);
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, length);
                }
                inputStream.close();
                outputStream.close();
                Toast.makeText(MainActivity.this, getString(R.string.cache_saved), Toast.LENGTH_LONG).show();
                return file.getAbsolutePath();
            }
        } catch (IOException ignored) {
        }
        return "";
    }

    private String getFileNameFromUri(Uri uri) {
        ContentResolver contentResolver = MainActivity.this.getContentResolver();
        String fileName = null;
        // 使用 ContentResolver 查询文件名
        try (Cursor cursor = contentResolver.query(uri, null, null, null, null)) {
            if (cursor != null && cursor.moveToFirst()) {
                int displayNameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                fileName = cursor.getString(displayNameIndex);
            }
        }
        return fileName;
    }

    public void RequestStoragePermission(Activity context) {
        // 文件读写权限检查
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            //多个权限一起申请
            ActivityCompat.requestPermissions(context, new String[]{
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE
            }, 1);
        }
        // 安卓11权限申请
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
            intent.setData(Uri.parse("package:" + getPackageName()));
            context.startActivity(intent);
        }
        //  String.valueOf(Environment.getExternalStorageDirectory());  // 获取环境目录，即/storage/emulated/0/
    }

    private void BindSettingWidgetCallbacks() {
        SharedPreferences sharedPreferences = getSharedPreferences("Settings", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        Button Button_SetDisplayScale = findViewById(R.id.SetDisplayScale);
        Button_SetDisplayScale.setOnClickListener(v -> {
            final EditText input = new EditText(MainActivity.this);
            input.setHint(R.string.please_enter_new_display_scale);
            input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
            new AlertDialog.Builder(MainActivity.this)
                    .setView(input)
                    .setPositiveButton(R.string.confirm, (dialog, which) -> {
                        String inputText = input.getText().toString().trim();
                        if (!inputText.isEmpty()) {
                            try {
                                int number = Integer.parseInt(inputText);
                                editor.putInt("DisplayScale", number);
                                editor.apply();
                            } catch (NumberFormatException e) {
                                Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.dismiss()).show();
        });

        Button Button_SetLandscapeDisplayScale = findViewById(R.id.SetLandscapeDisplayScale);
        Button_SetLandscapeDisplayScale.setOnClickListener(v -> {
            final EditText input = new EditText(MainActivity.this);
            input.setHint(R.string.please_enter_new_display_scale);
            input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
            new AlertDialog.Builder(MainActivity.this)
                    .setView(input)
                    .setPositiveButton(R.string.confirm, (dialog, which) -> {
                        String inputText = input.getText().toString().trim();
                        if (!inputText.isEmpty()) {
                            try {
                                int number = Integer.parseInt(inputText);
                                editor.putInt("LandscapeDisplayScale", number);
                                editor.apply();
                            } catch (NumberFormatException e) {
                                Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.dismiss()).show();
        });

        Button Button_BrowseCSS = findViewById(R.id.BrowseCSS);
        Button_BrowseCSS.setOnClickListener(view -> new Func_OpenWithExternal(MainActivity.this).openAssignFolder(REQUEST_CODE_NATIVE_FILE_CHOOSER));
        TextView TextView_CurrentCSSDisplay = findViewById(R.id.CurrentCSSDisplay);
        if (!sharedPreferences.getString("CSSPath", "").isEmpty()) TextView_CurrentCSSDisplay.setText(sharedPreferences.getString("CSSPath", ""));
        Button Button_RestoreCSS = findViewById(R.id.RestoreCSS);
        Button_RestoreCSS.setOnClickListener(view -> {
            TextView_CurrentCSSDisplay.setText(R.string.internal_default);
            editor.putString("CSSPath", "");
            editor.apply();
        });

        Button Button_SetPort = findViewById(R.id.SetPort);
        Button_SetPort.setOnClickListener(v -> {
            final EditText input = new EditText(MainActivity.this);
            input.setHint(R.string.please_enter_new_internal_server_port);
            input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
            new AlertDialog.Builder(MainActivity.this)
                    .setView(input)
                    .setPositiveButton(R.string.confirm, (dialog, which) -> {
                        String inputText = input.getText().toString().trim();
                        if (!inputText.isEmpty()) {
                            try {
                                int number = Integer.parseInt(inputText);
                                editor.putInt("Port", number);
                                editor.apply();
                            } catch (NumberFormatException e) {
                                Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.dismiss()).show();
        });

        Button Button_SetPadding = findViewById(R.id.SetPadding);
        Button_SetPadding.setOnClickListener(v -> {
            final EditText input = new EditText(MainActivity.this);
            input.setHint(R.string.please_input_new_padding);
            input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
            new AlertDialog.Builder(MainActivity.this)
                    .setView(input)
                    .setPositiveButton(R.string.confirm, (dialog, which) -> {
                        String inputText = input.getText().toString().trim();
                        if (!inputText.isEmpty()) {
                            try {
                                int number = Integer.parseInt(inputText);
                                editor.putInt("Padding", number);
                                editor.apply();
                            } catch (NumberFormatException e) {
                                Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.dismiss()).show();
        });

        Button Button_SetPaddingTop = findViewById(R.id.SetPaddingTop);
        Button_SetPaddingTop.setOnClickListener(v -> {
            final EditText input = new EditText(MainActivity.this);
            input.setHint(R.string.please_input_new_padding);
            input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
            new AlertDialog.Builder(MainActivity.this)
                    .setView(input)
                    .setPositiveButton(R.string.confirm, (dialog, which) -> {
                        String inputText = input.getText().toString().trim();
                        if (!inputText.isEmpty()) {
                            try {
                                int number = Integer.parseInt(inputText);
                                editor.putInt("PaddingTop", number);
                                editor.apply();
                            } catch (NumberFormatException e) {
                                Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            Toast.makeText(MainActivity.this, R.string.invalid_number, Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.dismiss()).show();
        });

        Switch Switch_AllowExternalAccess = findViewById(R.id.AllowExternalAccess);
        Switch_AllowExternalAccess.setChecked(sharedPreferences.getBoolean("AllowExternalAccess", false));
        Switch_AllowExternalAccess.setOnCheckedChangeListener((buttonView, isChecked) -> {
            editor.putBoolean("AllowExternalAccess", isChecked);
            editor.apply();
        });

        Switch Switch_AllowVolumeZoomControl = findViewById(R.id.AllowVolumeZoomControl);
        Switch_AllowVolumeZoomControl.setChecked(sharedPreferences.getBoolean("AllowVolumeZoomControl", true));
        Switch_AllowVolumeZoomControl.setOnCheckedChangeListener((buttonView, isChecked) -> {
            editor.putBoolean("AllowVolumeZoomControl", isChecked);
            editor.apply();
        });

    }
}